<?php

/**
 * 登录操作模型
 *
 * @author 煤老板 <meok23@sina.com>
 * @date   2017-06-07
 */

namespace app\admin\model;

use app\common\logic\Response;
use fw\base\Instance;
use fw\db\DB;
use fw\tool\Request;
use fw\tool\Session;
use fw\tool\Str;

class Login
{
    use Instance;

    /**
     * 缓存 identities /token 到cookie，同时更新数据的token。
     * 用于自动登录。
     *
     * @param array $args
     * @param int   $keep
     *
     * @return bool
     */
    private function _cacheToken($args, $keep = 0)
    {
        // 参数获取
        $keep = (int)$keep;
        ($keep > 7) && $keep = 7; // 最久只能缓存一周

        $manager_id = (int)Request::input($args, 'manager_id');
        $identities = Request::input($args, 'identities', 'trim');

        $token = md5(uniqid(rand(), true));
        $timeout = (int)strtotime(date('Ymd'));

        // 缓存自动登录信息到 cookie
        $value = "{$identities}^{$token}";
        if ($keep > 0) {
            $timeout += 86400 * $keep;
            $ret = setcookie('identities_token', $value, $timeout);
        } else {
            // 防止session掉线的时候导致登录被退出
            $timeout += 86400;
            $ret = setcookie('identities_token', $value);
        }
        if ($ret == false) {
            Response::log([501, 'Set cookie fail: identities_token.', ['identities_token' => $value]], [$args, $keep]);
            return false;
        }

        // 更新数据库 token
        $data = [
            'last_ip'   => ip2long(Request::clientIp()),
            'last_time' => time(),
            'token'     => $token,
            'timeout'   => $timeout,
        ];
        $affected_rows = DB::table('manager')->where('manager_id=:manager_id', [':manager_id' => $manager_id])->update($data);
        if ($affected_rows < 1) {
            Response::log([502, 'Update db fail.', ['identities_token' => $value]], [$args, $keep]);
            return false;
        }

        // 成功时返回
        return true;
    }

    /**
     * 缓存用户信息到session
     *
     * @param array $args
     *
     * @return bool
     */
    private function _cacheAuth($args)
    {
        // 参数获取
        $manager_id = (int)Request::input($args, 'manager_id');
        $name = Request::input($args, 'name', 'trim');
        $email = Request::input($args, 'email', 'trim');

        // 参数校验
        if ($manager_id < 1 || empty($name) || empty($email)) {
            return false;
        }

        // 缓存用户信息到 session
        Session::gi()->set('auth', [
            'manager_id' => $manager_id,
            'name'       => $name,
            'email'      => $email,
        ]);

        // 成功时返回
        return true;
    }

    /**
     * 从cookie取得数据，然后进行自动登录。
     *
     * @return bool
     */
    public function autoLogin()
    {
        // 参数获取
        $identities_token = Request::cookie('identities_token', 'trim');

        // 参数校验
        if (empty($identities_token)) {
            return false;
        }

        list($identities, $token) = explode('^', $identities_token);

        // 查询数据库
        $row = DB::table('manager')->where('identities=:identities', [':identities' => $identities])->selectRow();

        // 校验结果
        if (empty($row)) {
            // 用户不存在
            return false;
        } elseif ($token != $row['token']) {
            // token 不一致
            Response::log([400, 'Differ token.'], $identities_token);
            return false;
        } elseif (time() > $row['timeout']) {
            // token 过期
            return false;
        } elseif ($identities != Str::encrypt($row['email'], $row['email'])) {
            // identities 无效
            Response::log([400, 'Signs is invalid.'], $identities_token);
            return false;
        } else {
            $keep = ($row['timeout'] - time()) / 86400;
            if ($keep < 1) {
                $keep = 0;
            } else {
                $keep = ceil($keep);
            }
            $this->_cacheToken($row, $keep);
            $this->_cacheAuth($row);

            return true;
        }
    }

    /**
     * 登录
     *
     * @return array
     */
    public function login()
    {
        // 参数获取
        $email = Request::post('email', 'trim');
        $password = Request::post('password', 'trim');
        $keep = (int)Request::post('keep');

        // 参数校验
        $pattern = '/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/';
        if (empty($email) || preg_match($pattern, $email) < 1) {
            return Response::to([400, 'Parameter error, check email please.']);
        }
        if (empty($password)) {
            Response::to([400, 'Parameter error.']);
        }

        // 查询数据库
        $identities = Str::encrypt($email, $email);
        $row = DB::table('manager')->where('identities=:identities', [':identities' => $identities])->selectRow();

        // 校验结果
        if (empty($row) || $row['email'] != $email) {
            // 用户不存在
            return Response::to([404, 'The user have not found.']);
        } elseif ($row['password'] != Str::encrypt($password, $password)) {
            // 密码错误
            return Response::to([404, 'Password error.']);
        } elseif ($row['status'] != 1) {
            // 账号不可用
            return Response::to([400, 'The user account disabled.']);
        } else {
            $this->_cacheToken($row, $keep);
            $this->_cacheAuth($row);
        }

        return Response::to([0, 'Success.']);
    }

    /**
     * 退出登录
     */
    public function logout()
    {
        $check_auth = Session::gi()->has('auth');
        if ($check_auth == true) {
            Session::gi()->delete('auth');

            setcookie('identities_token', 'null', time() - 1);
        }
    }
}
